package com.softeem.score.manager.service.impl;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.softeem.score.manager.mapper.RecordScoreMapper;
import com.softeem.score.manager.service.RecordScoreService;
import com.softeem.score.model.dto.gradeDto.RecordScoreDto;
import com.softeem.score.model.entity.educational.GradeDetail;
import com.softeem.score.model.entity.educational.TeachingClass;
import com.softeem.score.model.vo.educational.GradeDetailVo;
import com.softeem.score.model.vo.educational.GradeVo;
import com.softeem.score.model.vo.school.MapVo;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.*;

@Service
public class RecordScoreServiceImpl implements RecordScoreService {

    @Autowired
    private RecordScoreMapper recordScoreMapper;

    @Override
    public List<MapVo> findAllTeachingClassByCourseIdAndTeacherId(Long courseId, Long teacherId, String academicYear, Integer semester) {
        return recordScoreMapper.findAllTeachingClassByCourseIdAndTeacherId(courseId, teacherId, academicYear, semester);
    }

    @Override
    public PageInfo<GradeVo> findGradeInfoByPage(Integer pageNum, Integer pageSize, Long teachingClassId) {
        PageHelper.startPage(pageNum, pageSize);
        List<GradeVo> gradeVoList = recordScoreMapper.findGradeInfoByPage(teachingClassId);
        for (GradeVo gradeVo : gradeVoList) {
            BigDecimal totalScore = gradeVo.getTotalScore();
            if (totalScore != null && totalScore.compareTo(BigDecimal.valueOf(60)) < 0) {
                gradeVo.setIsMakeupExam(1);
            }
        }
        for (GradeVo gradeVo : gradeVoList) {
            gradeVo.setGradeDetailVoList(recordScoreMapper.findGradeDetailById(gradeVo.getId()));
        }
        System.out.println("gradeVoList = " + gradeVoList);
        return new PageInfo<>(gradeVoList);
    }

    @Override
    public void saveGradeDetailInfo(List<GradeDetail> gradeDetailList) {
        for (GradeDetail gradeDetail : gradeDetailList) {
            if (gradeDetail.getGradeId() != null && gradeDetail.getScore() != null) {
                recordScoreMapper.updateGradeDetailInfo(gradeDetail);
            }
        }
    }

    @Override
    public void updateTotalScore(Long id, BigDecimal totalScore) {
        recordScoreMapper.updateTotalScore(id, totalScore);
    }

    @Override
    public ResponseEntity<byte[]> exportData(RecordScoreDto recordScoreDto) {
        TeachingClass teachingClass = recordScoreMapper.findTeachingClassById(recordScoreDto.getTeachingClassId());
        List<GradeVo> gradeVoList = recordScoreMapper.findGradeInfoByPage(recordScoreDto.getTeachingClassId());
        for (GradeVo gradeVo : gradeVoList) {
            gradeVo.setGradeDetailVoList(recordScoreMapper.findGradeDetailById(gradeVo.getId()));
        }
        try {
            // 创建 Excel 工作簿
            Workbook workbook = new XSSFWorkbook();
            Sheet sheet = workbook.createSheet("学生成绩");
            // 创建表头行
            Row headerRow = sheet.createRow(0);
            Set<String> headerSet = new LinkedHashSet<>(); // 使用 LinkedHashSet 保证表头信息按照插入顺序排列
            headerSet.add("学号");
            headerSet.add("姓名");
            for (GradeVo gradeVo : gradeVoList) {
                for (GradeDetailVo gradeDetailVo : gradeVo.getGradeDetailVoList()) {
                    headerSet.add(gradeDetailVo.getGradeComponentItemName());
                }
            }
            headerSet.add("总成绩");
            // 将表头信息按照顺序写入表格
            int columnIndex = 0;
            for (String header : headerSet) {
                Cell cell = headerRow.createCell(columnIndex++);
                cell.setCellValue(header);
            }
            // 添加学生数据到表格中
            int rowNum = 1; // 从第二行开始写入数据，因为第一行是表头
            for (GradeVo gradeVo : gradeVoList) {
                Row row = sheet.createRow(rowNum++);
                row.createCell(0).setCellValue(gradeVo.getStudentNumber()); // 学号
                row.createCell(1).setCellValue(gradeVo.getStudentName()); // 姓名
                int cellIndex = 2; // 从第三列开始写入成绩数据
                for (GradeDetailVo gradeDetailVo : gradeVo.getGradeDetailVoList()) {
                    BigDecimal score = gradeDetailVo.getScore();
                    if (score != null) {
                        row.createCell(cellIndex++).setCellValue(score.doubleValue());
                    }
                }
                if (gradeVo.getTotalScore() != null) {
                    row.createCell(columnIndex - 1).setCellValue(gradeVo.getTotalScore().doubleValue());
                }
            }
            // 将 Excel 数据写入字节数组输出流
            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
            workbook.write(outputStream);
            // 设置响应头
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
            headers.setContentDispositionFormData("attachment", recordScoreDto.getAcademicYear() + "年第" + recordScoreDto.getSemester() + "学期" + teachingClass.getName() + "班学生成绩表.xlsx");
            // 返回响应实体
            return new ResponseEntity<>(outputStream.toByteArray(), headers, HttpStatus.OK);
        } catch (IOException e) {
            e.printStackTrace();
            return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
        }
    }

    @Transactional
    @Override
    public void importData(MultipartFile file, Long teachingClassId) {
        try {
            EasyExcel.read(file.getInputStream(), new AnalysisEventListener<Map<Integer, String>>() {
                // 定义一个变量用于保存表头信息
                final Map<Integer, Object> headerMap = new HashMap<>();
                @Override
                public void invokeHeadMap(Map<Integer, String> headMap, AnalysisContext context) {
                    // 处理表头信息，获取每列的列名
                    for (Map.Entry<Integer, String> entry : headMap.entrySet()) {
                        Integer columnIndex = entry.getKey();
                        String columnName = entry.getValue();
                        if (!columnName.equals("学号") && !columnName.equals("姓名") && !columnName.equals("总成绩")) {
                            headerMap.put(columnIndex, recordScoreMapper.findGradeCompontCourseIdByName(columnName, teachingClassId));
                        } else {
                            headerMap.put(columnIndex, columnName);
                        }
                    }
                }

                boolean isValidScore(String cellValue) {
                    return cellValue != null && new BigDecimal(cellValue).compareTo(BigDecimal.ZERO) >= 0 &&
                            new BigDecimal(cellValue).compareTo(BigDecimal.valueOf(100)) <= 0;
                }

                @Override
                public void invoke(Map<Integer, String> rowData, AnalysisContext context) {
                    // 处理数据行
                    for (Map.Entry<Integer, String> entry : rowData.entrySet()) {
                        Integer columnIndex = entry.getKey();
                        String cellValue = entry.getValue();
                        // 获取对应的表头列名
                        Object columnName = headerMap.get(columnIndex);
                        Long gradeId = recordScoreMapper.findgradeIdByStudentNumberAndTeachingClassId(rowData.get(0), teachingClassId);
                        if (gradeId != null) {
                            if (columnName instanceof Long) {
                                if (isValidScore(cellValue)) {
                                    GradeDetail gradeDetail = new GradeDetail();
                                    gradeDetail.setGradeId(gradeId);
                                    gradeDetail.setGradeComponentCourseId((Long) columnName);
                                    gradeDetail.setScore(new BigDecimal(cellValue));
                                    recordScoreMapper.updateGradeDetailInfo(gradeDetail);
                                }
                            } else if (columnName.equals("总成绩")) {
                                if (isValidScore(cellValue)) {  //总成绩有值
                                    recordScoreMapper.updateTotalScore(gradeId, new BigDecimal(cellValue));
                                } else {
                                    List<GradeDetailVo> gradeDetailVoList = recordScoreMapper.findGradeDetailById(gradeId);
                                    if (gradeDetailVoList != null && gradeDetailVoList.size() > 0) {
                                        BigDecimal totalScore = BigDecimal.ZERO;
                                        for (GradeDetailVo gradeDetailVo : gradeDetailVoList) {
                                            if (gradeDetailVo.getScore() != null) {
                                                totalScore = totalScore.add(gradeDetailVo.getScore().multiply(gradeDetailVo.getWeightage()));
                                            }
                                        }
                                        recordScoreMapper.updateTotalScore(gradeId, totalScore);
                                    }
                                }
                            }
                        }
                    }
                }
                @Override
                public void doAfterAllAnalysed(AnalysisContext context) {
                    // 所有数据解析完成后的操作
                    String sheetName = context.readSheetHolder().getSheetName();
                    System.out.println("当前工作表名称：" + sheetName);
                }
            }).sheet().doRead();
            // 调用read方法读取excel数据
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}
